package log

import (
	"gbox-one-machine/conf"
	"io"
	"os"
	"time"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"strings"
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
)

// Logger for zap log
var Logger *zap.SugaredLogger

// InitLogger create logger
func InitLogger(cf *conf.Config) error {
	encoderConf := zapcore.EncoderConfig{
		MessageKey:  "msg",
		LevelKey:    "level",
		EncodeLevel: zapcore.CapitalLevelEncoder,
		TimeKey:     "ts",
		EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
			enc.AppendString(t.Format("2006-01-02 15:04:05"))
		},
		CallerKey:    "file",
		EncodeCaller: zapcore.ShortCallerEncoder,
		EncodeDuration: func(d time.Duration, enc zapcore.PrimitiveArrayEncoder) {
			enc.AppendInt64(int64(d) / 1000000)
		},
	}

	encoder := zapcore.NewJSONEncoder(encoderConf)
	consoleEncoder := zapcore.NewConsoleEncoder(encoderConf)

	debugLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl == zapcore.DebugLevel
	})

	infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl >= zapcore.InfoLevel
	})

	errorLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl >= zapcore.ErrorLevel
	})

	zapCores := []zapcore.Core{}

	logWriter, err := fileWriter(cf.Log.Path + "/info.log")
	if err != nil {
		return err
	}

	errorWriter, err := fileWriter(cf.Log.Path + "/error.log")
	if err != nil {
		return err
	}

	debugWriter, err := fileWriter(cf.Log.Path + "/debug.log")
	if err != nil {
		return err
	}

	zapCores = append(zapCores, zapcore.NewCore(encoder, zapcore.AddSync(logWriter), infoLevel))
	zapCores = append(zapCores, zapcore.NewCore(consoleEncoder, zapcore.Lock(os.Stdout), infoLevel))
	zapCores = append(zapCores, zapcore.NewCore(encoder, zapcore.AddSync(errorWriter), errorLevel))

	if cf.App.Debug {
		zapCores = append(zapCores, zapcore.NewCore(encoder, zapcore.AddSync(debugWriter), debugLevel))
		zapCores = append(zapCores, zapcore.NewCore(consoleEncoder, zapcore.Lock(os.Stdout), debugLevel))
	}

	core := zapcore.NewTee(zapCores...)

	log := zap.New(core, zap.AddCaller(), zap.Development(), zap.AddStacktrace(debugLevel))
	Logger = log.Sugar()

	return nil
}

func fileWriter(filename string) (io.Writer, error) {
	hook, err := rotatelogs.New(
		strings.Replace(filename, ".log", "", -1) + "-%Y%m%d%H.log",
	)
	if err != nil {
		return nil, err
	}

	return hook, nil
}
